/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package libraries;

import java.text.DecimalFormat;
import javax.swing.text.*;

/**
 *
 * @author aeguzkiza
 */
public class JTextFieldFilter extends PlainDocument {
    public static final String LOWERCASE  = "abcdefghijklmnopqrstuvwxyz";
    public static final String UPPERCASE  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String ALPHA   = LOWERCASE + UPPERCASE;
    public static final String NUMERIC = "0123456789";
    public static final String FLOAT = NUMERIC + ".";
    public static final String ALPHA_NUMERIC = ALPHA + NUMERIC;

    private int decimal = 2;
    private int limit = 0;
    private int maxValue = 0;
    private int extraLimit_comma = 0;
    private int extraLimit_neg = 0;
    private boolean removeLastChar = false;

    private boolean toUppercase = false;
    private boolean toLowercase = false;
    protected String acceptedChars = null;
    protected boolean negativeAccepted = false;
    protected boolean symbolAccepted = false;
    protected boolean spaceAccepted = false;


    public JTextFieldFilter() {
        this(ALPHA_NUMERIC);
    }
    public JTextFieldFilter(String acceptedchars) {
        this.acceptedChars = acceptedchars;
    }

    public void setNegativeAccepted(boolean negativeaccepted) {        
        if (negativeaccepted && (acceptedChars.equals(NUMERIC) || acceptedChars.equals(FLOAT) || acceptedChars.equals(ALPHA_NUMERIC))){
            this.negativeAccepted = negativeaccepted;
            acceptedChars += "-";
        }
    }
    public void setSymbolAccepted(boolean symbolAccepted) {
        if (symbolAccepted){
            this.symbolAccepted = symbolAccepted;
            acceptedChars += "?";
        }
    }
    public void setSpaceAccepted(boolean spaceAccepted) {
        if (spaceAccepted){
            this.spaceAccepted = spaceAccepted;
            acceptedChars += " ";
        }
    }
    public void setMaxDecimal(int decimal) {
       this.decimal = decimal;
    }
    public void setLimit(int limit) {
        this.limit = limit;
    }
    public void setMaxValue(int maxValue) {
       if (maxValue != 0 && (acceptedChars.equals(NUMERIC) || acceptedChars.equals(FLOAT) || acceptedChars.equals(FLOAT + "-"))){
            System.out.println("MaxValue: "+maxValue);
            this.maxValue = maxValue;
       }
    }
    public void setUpperCase(boolean toUppercase) {
        this.toUppercase = toUppercase;
    }
    public void setLowerCase(boolean toLowercase) {
        this.toLowercase = toLowercase;
    }
    public void insertString(int offset, String  str, AttributeSet attr) throws BadLocationException {
        this.extraLimit_comma = 0;  // Don't has comma.
        this.extraLimit_neg = 0;  // Don't has comma.
        String oldText = getText(0, getLength());
        String futureString = new StringBuffer(oldText).insert(offset, str).toString(); // Get the resulting teorical String after keypress.
        //System.out.println("futureString: "+futureString);

        if (str == null) return;
        
        if(!acceptedChars.contains(ALPHA_NUMERIC) && !acceptedChars.contains("?")){   // All chars allowed for ALPHA_NUMERIC.
            for (int i=0; i < str.length(); i++) {  // Filter to accepted chars.
                if (this.acceptedChars.indexOf(str.valueOf(str.charAt(i))) == -1)
                    return;
            }
        }
        if(acceptedChars.contains(ALPHA)){ // Text char allowed.
            if (toUppercase == true)
                str = str.toUpperCase();
            else if (toLowercase == true)
                str = str.toLowerCase();
        }else{    // Numeric char allowed.
            // Set extra length for "no numeric" characters.                        
            if (futureString.contains(".")) {
                this.extraLimit_comma = 1;  // It will has comma.
            }
            if(futureString.contains("-")){
                this.extraLimit_neg = 1;  // It will has comma.
            }
            System.out.println("FutureString1: "+futureString);
            System.out.println("It's comma: "+extraLimit_comma);
            System.out.println("It's minus: "+extraLimit_neg);
             
            if (acceptedChars.contains(FLOAT)) {
                String text = futureString;
                int commaCount = text.split("\\.",-1).length-1;   // How many times comma is repeated?
                System.out.println(commaCount);
                if (commaCount > 1) {   // Comma just typed.
                    System.out.println("Several comma typed");
                    return;
                }else if(futureString.contains(".") && (futureString.length()-1 - futureString.lastIndexOf(".")) > decimal){
                    //System.out.println("Decimals: "+(futureString.length()-1 - futureString.lastIndexOf(".")));
                    System.out.println("Too many decimals");
                    return;
                }else if(futureString.contains("-.")){
                    System.out.println("Comma typed after minus");
                    return;
                }else if(futureString.substring(offset).equals(".")){   // If "comma" it's at the end of the String, add a char.
                    System.out.println("Comma at the end of String");
                    this.removeLastChar = true;
                    str += 0;
                }                
            }
            if (negativeAccepted && str.indexOf("-") != -1) {   // Minus just typed.
                if (str.indexOf("-") != 0 || offset != 0 ) {    // Minus isn't at start of the String.
                    return;
                }else if(offset == oldText.length()){   // If "minus" it's at the end of the String, add a char.
                    this.removeLastChar = true;
                    str += 0;
                }
            }
            futureString = new StringBuffer(oldText).insert(offset, str).toString(); // Refresh the resulting teorical String after keypress.
            System.out.println("FutureString2: "+futureString);

            // Limit filed by its value.
            if (this.maxValue != 0){
                Float futureInt = Float.valueOf(futureString.trim()).floatValue();
                if (futureInt.compareTo(Float.valueOf(this.maxValue)) > 0 || futureInt.compareTo(Float.valueOf(-this.maxValue)) < 0) {    // The limit is absolute.
                    return;
                }
            }
            // Restore the last character added.
            //System.out.println("removeLastChar: "+this.removeLastChar);
            if(this.removeLastChar == true){
                str = str.substring(0, str.length()-1);
                this.removeLastChar = false;   // restore default value.
            }
            System.out.println("Current keyPress value: "+str);    // Comma just typed.
        }
        // Limit field by its length.
        //System.out.println("Current length: "+futureString.length()+" (Limit: "+this.limit+" + ExtraLimit_comma : "+extraLimit_comma+" + ExtraLimit_neg: "+extraLimit_neg+")");    // Comma just typed.
        int totalLimit = this.limit+extraLimit_comma+extraLimit_neg;
        if (this.limit != 0 && (futureString.length() > totalLimit)) {
                return;
        }        
        super.insertString(offset, str, attr);
    }
}
